
#define POLICY_TEST(h, p)	((h)->mmu->policy & (p))
#define M_TLBQ(h)			((h)->mmu->tlb_q)
#define M_TLB				((h)->mmu->tlb)
#define M_TLBWAIT(h)		((h)->mmu->tlb_delay)

#define M_CACHE(h, l)		((h)->mmu->L ## l)
struct mmu_queue {
	sim_size	count;
	mmu_op		*head;
	mmu_op		*tail;
};

static
inline
sim_priv get_ring(HOST *h) {
	return GET_SR_PRIV(R_LOAD(h, cp0, kCP0Reg_SR));
}

static
inline
sim_priv set_ring(HOST *h, sim_priv r) {
	SET_SR_PRIV(R_LOAD(h, cp0, kCP0Reg_SR), r);
}

static
inline
sim_addr get_asid(HOST *h) {
	// Fetch the ASID field from CP0:EntryHi
	return GET_ASID(R_LOAD(h, cp0, kCP0Reg_EntryHi));
}

static
inline
void set_asid(HOST *h, sim_addr asid) {
	// Set the ASID in field CP0:EntryHi
	SET_ASID(R_LOAD(h, cp0, kCP0Reg_EntryHi), asid);
}

static
inline
map_type get_map(HOST *h) {
	if(R_TEST(h, cp0, kCP0Reg_SR, SR_ERROR_LEVEL))
		return MAP_ECC;
	
	if(POLICY_TEST(h, POLICY_MAP_TLB))
		return MAP_TLB;
		
	if(POLICY_TEST(h, POLICY_MAP_FIXED))
		return MAP_FIXED;

	return MAP_NONE;
}

static
inline
void mmu_pushq(mmu_q *q, mmu_op *op) {
	if(q->tail)
		q->tail->next = op;
	else
		q->head = q->tail = op;
	op->next = NULL;
}

static
inline
mmu_op *mmu_popq(mmu_q *q) {
	mmu_op *op = q->head;
	if(q->head)
		q->head = q->head->next;
	else
		q->tail = NULL;
	
	return op;
}

